<?php
/**
* Renders classes.
*
* @version	$Id: PhpdocHTMLClassRenderer.php,v 1.4 2000/12/03 22:37:37 uw Exp $
*/
class PhpdocHTMLClassRenderer extends PhpdocHTMLDocumentRenderer {

	/**
	* Internal array of "&nbsp;" strings to format HTML output.
	*
	* @var	array	$indent
	*/
	var $indent = array();

	/**
	* Array of variables found in the xml document.
	*
	* @var	array	$variables
	*/
	var $variables = array();

	/**
	* Sets the xml and template root directory.
	* 
	* @param	string	XML file path
	* @param	string	Template file path
	* @param	string	Name of the current application
	* @param	string	Filename extension
	* @see	setPath(), setTemplateRoot()
	*/
	function PhpdocHTMLClassRenderer($path, $templateRoot, $application, $extension = ".html") {

		$this->setPath($path);
		$this->setTemplateRoot($templateRoot);
		$this->application = $application;
		$this->file_extension = $extension;
		
		$this->accessor = new PhpdocClassAccessor;
		$this->tpl = new IntegratedTemplate($this->templateRoot);
		$this->fileHandler = new PhpdocFileHandler;

	} // end constructor

	/**
	* Renders a class.
	*
	* @param	string	XML source file
	* @param	string	Name of the HTML target file.
	* @access	public
	*/	
	function renderClass($xmlfile, $htmlfile = "") {

		$this->tpl->loadTemplatefile("class.html");	
		if ("" == $htmlfile)
			$htmlfile = substr($xmlfile, 6, -4) . $this->file_extension;

		$this->accessor->loadXMLFile($this->path.$xmlfile);
		
		$this->renderSubclasses();
		$this->renderInherited();
		$this->renderFunctions();
		$this->renderVariables();
		$this->renderUses();
		$this->renderConstants();
		
		$class = $this->accessor->getClassdata();
		$tplvars = array();

		$tplvars["CLASS_FILE"] 		= $class["file"]["value"];
		$tplvars["CLASS_NAME"] 		= $class["name"];
		$tplvars["CLASS_ACCESS"]	= $class["access"];
		$tplvars["CLASS_PACKAGE"]	= $class["package"];

		if ("" != $class["extends"])
			$tplvars["CLASS_EXTENDS"] = sprintf('extends <a href="%s">%s</a>', 
																						$class["extends"].$this->file_extension, 
																						$class["extends"]
																					);
			
		$tplvars["CLASS_UNDOC"] 	= ("true" == $class["undoc"]) ? $this->undocumented : "";
		
		$tplvars["CLASS_ABSTRACT"] = ("true" == $class["abstract"]) ? "abstract" : "";
		$tplvars["CLASS_STATIC"]	 = ("true" == $class["static"]) ? "static" : "";
		$tplvars["CLASS_FINAL"] 	 = ("true" == $class["final"]) ? "final" : "";
		
		$tplvars["CLASS_TREE"] 		= $this->getClasstree($class["name"]);
		
		if (isset($class["doc"]["link"]))
			$this->renderLinks($class["doc"]["link"], "class_");
			
		if (isset($class["doc"]["author"]))
			$this->renderAuthors($class["doc"]["author"], "class_");
			
		if (isset($class["doc"]["see"]))
			$this->renderSee($class["doc"]["see"], "class_");
		
		$fields = array( 	"version", "deprecated", "copyright",	"since", "magic");
		reset($fields);
		while (list($k, $field) = each($fields)) 
			if (isset($class["doc"][$field])) {
				$this->tpl->setCurrentBlock("class_".strtolower($field));
				$this->tpl->setVariable(strtoupper($field), $class["doc"][$field]["value"]);
				$this->tpl->parseCurrentBlock();
			}

		$fields = array( "description", "shortdescription" );

		reset($fields);
		while (list($k, $field)=each($fields)) 
			if (isset($class["doc"][$field]))
				$tplvars["CLASS_".strtoupper($field)] = $this->encode($class["doc"][$field]["value"]);

		$this->tpl->setCurrentBlock("__global__");
		$this->tpl->setVariable($tplvars);
		$this->tpl->setVariable("APPNAME", $this->application);

		$this->fileHandler->createFile($this->path.$htmlfile, $this->tpl->get() );
		$this->tpl->free();	

	} // end func renderClass

	

	/**
	* Renders a list of inherited elements.
	*
	* @see	renderInheritedElements()
	*/
	function renderInherited() {

		$this->renderInheritedElements(	$this->accessor->getInheritedFunctions(),
																		"inheritedfunctions",
																		"function"
																	);
																	
		$this->renderInheritedElements( $this->accessor->getInheritedVariables(),
																		"inheritedvariables",
																		"variable"
																	);

		$this->renderInheritedElements( $this->accessor->getInheritedConstants(),
																		"inheritedconstants",
																		"constant"
																	);

		$this->renderInheritedElements(	$this->accessor->getInheritedUses(),
																		"inheriteduses",
																		"uses"
																	);

	} // end func renderInherited

	/**
	* Renders a list of a certain inherited element.
	*
	* @param	array		List of inherited elements.
	* @param	string	Templateblockname
	* @param	string	Element type: function, variable...
	* @see	renderInherited()
	*/
	function renderInheritedElements($inherited, $block, $type) {
		
		if (0 == count($inherited))
			return;

		$this->tpl->setCurrentBlock($block);

		reset($inherited);
		while (list($source, $elements) = each($inherited)) {
			
			$value = "";
			
			reset($elements);
			while (list($k, $element) = each($elements))
				$value .= sprintf('<a href="%s#%s_%s">%s</a>, ', 
															$source.$this->file_extension,
															$type, 
															$element, 
															$element
													);
			$value = substr($value, 0, -2);
			
			$this->tpl->setVariable("SOURCE", $source);
			$this->tpl->setVariable("ELEMENTS", $value);
			$this->tpl->parseCurrentBlock();
		}

	} // end func renderInheritedElements

	/**
	* Renders a list of direct known subclasses.
	*/
	function renderSubclasses() {
		
		$subclasses = $this->accessor->getSubclasses();
		if (0 == count($subclasses)) 
			return;
		
		$elements = "";
		reset($subclasses);
		while (list($k, $subclass) = each($subclasses))
			$elements .= sprintf('<a href="%s">%s</a>, ', $subclass.$this->file_extension, $subclass);
		
		$elements	= substr($elements, 0, -2);
		
		if ("" != $elements) {
		
			$this->tpl->setCurrentBlock("subclasses");
			$this->tpl->setVariable("ELEMENTS", $elements);
			$this->tpl->parseCurrentBlock();
		}

	} // end func renderSubclasses

	/**
	* Adds a summary and a detailed list of all variables to the template.
	*
	* @see	renderVariableSummary(), renderVariableDetail()
	*/
	function renderVariables() {
		
		$this->variables["private"] = $this->accessor->getVariablesByAccess("private");
		$this->variables["public"] 	= $this->accessor->getVariablesByAccess("public");
		
		if (0 == count($this->variables["private"]) && 0 == count($this->variables["public"]))
			return;
		
		$this->renderVariableSummary();
		$this->renderVariableDetail();

		$this->variables = array();

	} // end func renderVariables

	/**
	* Adds a summary of all variables to the template.
	* 
	* The function assumes that there is a block named "variablesummary" and
	* within it a block names "variablesummay_loop" in the template.
	*
	* @see	renderVariableDetail()
	*/	
	function renderVariableSummary() {

		reset($this->accessModifiers);
		while (list($k, $access) = each($this->accessModifiers)) {

			if (0 == count($this->variables[$access]))
				continue;
				
			$this->tpl->setCurrentBlock("variablesummary_loop");
			
			reset($this->variables[$access]);
			while (list($name, $variable) = each($this->variables[$access])) {
				
				$this->tpl->setVariable("NAME", $name);
				$this->tpl->setVariable("TYPE", $variable["type"]);
				
				if (isset($variable["doc"]["shortdescription"]))
					$this->tpl->setVariable("SHORTDESCRIPTION", $this->encode($variable["doc"]["shortdescription"]["value"]));
			
				$this->tpl->parseCurrentBlock();				
				
			}
			
			$this->tpl->setCurrentBlock("variablesummary");
			$this->tpl->setVariable("ACCESS", ucfirst($access));
			$this->tpl->parseCurrentBlock();
			
		}

	} // end func renderVariableSummary

	/**
	* Adds a detailed list of all variables to the template.
	* 
	* The function assumes that there is a block named "variabledetails"
	* and within it a block names "variablesdetails_loop" in the template.
	*
	* @see	renderVariableSummary()
	*/	
	function renderVariableDetail() {
		
		reset($this->accessModifiers);
		while (list($k, $access) = each($this->accessModifiers)) {

			if (0 == count($this->variables[$access]))
				continue;

			reset($this->variables[$access]);
			while (list($name, $variable)=each($this->variables[$access])) {
			
				$tplvars = array();
				$tplvars["NAME"] 		=	$variable["name"];
				$tplvars["ACCESS"] 	= $variable["access"];
				$tplvars["TYPE"] 		= $variable["type"];
				$tplvars["VALUE"]		= htmlentities($variable["value"]);

				if ("true" == $variable["undoc"]) 
					$tplvars["UNDOC"] = $this->undocumented;

				if ("true" == $variable["static"])
					$tplvars["STATIC"] = "static";

				if ("true" == $variable["final"])
					$tplvars["FINAL"] = "final";

				if (isset($variable["doc"]["shortdescription"]))
					$tplvars["SHORTDESCRIPTION"] = $this->encode($variable["doc"]["shortdescription"]["value"]);

				if (isset($variable["doc"]["description"]))
					$tplvars["DESCRIPTION"] = $this->encode($variable["doc"]["description"]["value"]);

				$this->renderCommonDocfields("variabledetails_", $variable);

				$this->tpl->setCurrentBlock("variabledetails_loop");	
				$this->tpl->setVariable($tplvars);
				$this->tpl->parseCurrentBlock();	

			}

			$this->tpl->setCurrentBlock("variabledetails");
			$this->tpl->setVariable("ACCESS", ucfirst($access) );
			$this->tpl->parseCurrentBlock();

		}

	} // end func renderVariableDetail

	/**
	* Returns a html string that shows the class tree.
	*
	* @param	string	name of the current class
	* @return	string	HTML that shows the tree
	*/
	function getClasstree($class) {
		
		$path = $this->accessor->getClasstree();
		$level = 0;
		$num = count($path) - 1;
		
		for ($i = $num; $i >= 0; --$i) {

			$indent = $this->getIndent($level);

			if ($level > 0)
				$value.= sprintf("%s |<br>%s+-- ", $indent, $indent);

			$value.= sprintf('<a href="%s">%s</a><br>', 
												$path[$i].$this->file_extension,
												$path[$i]
											);
			++$level;
			
		}

		$indent = $this->getIndent($level);

		if ($level > 0)
			$value.= sprintf("%s |<br>%s+-- ", $indent, $indent);

		$value.= sprintf('%s<br>', $class);

		return $value;
	} // end func getClasstree

	/**
	* Returns a certain number of "&nbsp;"s.
	*
	* @param	int	number of "&nbsp;" required.
	* @see		$indent
	* @return	string	A string with the requested number of nunbreakable html spaces
	*/
	function getIndent($level) {

		if (!isset($this->indent[$level])) {

			$html = "";
			for ($i = 0; $i < $level; ++$i)
				$html .= "&nbsp;&nbsp;";

			$this->indent[$level] = $html;

		}

		return $this->indent[$level];
	} // end func getIndent

} // end class PhpdocHTMLClassRenderer

?>